
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
LIBRARY lpm;
USE lpm.lpm_components.ALL;

ENTITY Ifetch IS
	PORT(	SIGNAL Instruction	: OUT	STD_LOGIC_VECTOR( 31 DOWNTO 0 );
        	SIGNAL PC_plus_4_out	: OUT	STD_LOGIC_VECTOR( 7 DOWNTO 0 );
        	SIGNAL Add_result		: IN 	STD_LOGIC_VECTOR( 7 DOWNTO 0 );
        	SIGNAL Branch 			: IN 	STD_LOGIC;
        	SIGNAL Zero				: IN 	STD_LOGIC;
      	SIGNAL PC_out			: OUT	STD_LOGIC_VECTOR( 7 DOWNTO 0 );
        	SIGNAL clock, reset	: IN 	STD_LOGIC);
END Ifetch;

ARCHITECTURE behavior OF Ifetch IS
-- Incluido para FPGA com memória sincrona
	component rom
		PORT(
			address	: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
			clock		: IN STD_LOGIC  := '1';
			q			: OUT STD_LOGIC_VECTOR (31 DOWNTO 0));
	end component;
-- ***************************************
	SIGNAL PC, PC_plus_4		: STD_LOGIC_VECTOR( 9 DOWNTO 0 );
	SIGNAL next_PC, next_PC_0	: STD_LOGIC_VECTOR( 7 DOWNTO 0 );
BEGIN

rom_inst : rom
	PORT MAP (
		address	=> PC( 9 downto 2 ),								--next_PC_0( 7 DOWNTO 0 ),
		q			=> Instruction,
		clock		=> clock
	);														--next_PC_0 <= next_PC when reset = '0' ELSE "00000000";
	-- copia os sinais de saida permitindo a leiturande dentro do modulo
		PC_out			<= PC( 7 DOWNTO 0 );
		PC_plus_4_out	<= PC_plus_4( 7 DOWNTO 0 );
	--incrementa o pc em 4        
      PC_plus_4( 9 DOWNTO 2 )	<= PC( 9 DOWNTO 2 ) + 1;
      PC_plus_4( 1 DOWNTO 0 )	<= "00";
	-- Mux para selecionar o Branch ou PC + 4        
		next_PC	<= Add_result  
			WHEN ( ( Branch = '1' ) AND ( Zero = '1' ) ) 
			ELSE   PC_plus_4( 9 DOWNTO 2 );

	-- guarda PC no regiatrador e carrega o proximo PC na borda de clock
	PROCESS
		BEGIN
			WAIT UNTIL ( clock'EVENT ) AND ( clock = '1' );
			IF reset = '1' THEN
				   PC <= "0000000000" ; 
			ELSE 
				   PC( 9 DOWNTO 2 ) <= next_PC;
			END IF;
	END PROCESS;
END behavior;


